package com.example.demo.base;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 全局的的异常拦截器（拦截所有的控制器）（带有@RequestMapping注解的方法上都会拦截）
 * @author zixiaojun
 * @date 2018/11/21
 * @copyright Moli Teams
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 拦截方法参数校验异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public BaseResponse handleConstraintViolationException(ConstraintViolationException cve){
        Set<ConstraintViolation<?>> cves = cve.getConstraintViolations();
        List<String> errors=new ArrayList<>();
        for (ConstraintViolation<?> constraintViolation : cves) {
            String message="";
            String path=constraintViolation.getPropertyPath().toString();
            if(StringUtils.isNotBlank(path)){
                String[] arr=path.split("\\.");
                if(arr!=null&&arr.length==2) {
                    message += arr[1]+" ";
                }
            }
            message+=constraintViolation.getMessage();
            errors.add(message);
        }
        String errMessage=String.format("%s:[%s]", ComStatusCodeEnum.COM_ERROR.getMessage(),StringUtils.join(errors,","));
        logger.error(errMessage,cve);
        return new BaseResponse(ComStatusCodeEnum.COM_ERROR.getCode(),errMessage);
    }

    /**
     * 拦截错误请求地址
     */
    @ExceptionHandler(value = {NoHandlerFoundException.class})
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public BaseResponse handleRequestMapping(Exception e) {
        logger.error("请求地址异常:", e);
        return new BaseResponse(ComStatusCodeEnum.COM_ERROR.getCode(), e.getMessage());
    }

    /**
     * 拦截参数校验异常
     */
    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseResponse handle(Exception e) {
        logger.error("参数异常:", e);
        return new BaseResponse(ComStatusCodeEnum.COM_ERROR.getCode(), e.getMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public BaseResponse notFount(RuntimeException e) {
        logger.error("拦截未知的运行时异常:", e);
        return new BaseResponse(ComStatusCodeEnum.COM_ERROR.getCode(), ComStatusCodeEnum.COM_ERROR.getMessage());
    }

    /**
     * 拦截未知的异常
     */
    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public BaseResponse notFount(Throwable e) {
        logger.error("拦截未知的异常:", e);
        return new BaseResponse(ComStatusCodeEnum.COM_ERROR.getCode(), ComStatusCodeEnum.COM_ERROR.getMessage());
    }

}
